package com.mapler.scrapper;

import com.mapler.ui.*;
import com.mapler.model.SModel;
import com.mapler.service.INotifier;
import com.mapler.utility.HttpHelper;
import com.mapler.utility.IConstant;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import javax.swing.SwingUtilities;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Node;

/**
 *
 * @author none
 */
public class ScrapperEngineUI extends javax.swing.JPanel implements INotifier {

    public ScheduledExecutorService emailExecutor = Executors.newScheduledThreadPool(10);
    protected ScheduledFuture<?> emailFuture = null;
    private String username;
    private String password;
    private SModel sModel;
    private static Logger log = Logger.getLogger(EngineUI.class);
    private INotifier iNotifier;
    private ScrapperWorker scrapperWorker;
    private String userType;
    private String userId;

    public ScrapperEngineUI(String username, String password, String userType, String userId) {
        this.username = username;
        this.password = password;
        this.userType = userType;
        this.userId = userId;
        initComponents();
        if (!StringUtils.equals(userType, "8")) {
            jBDownload.setVisible(false);
            jLBDate.setVisible(false);
            jTFDownload.setVisible(false);
            jCBUpdate.setVisible(false);
            jCBStore.setVisible(false);
        }
        initSettings();
    }

    public SModel getsModel() {
        if (sModel == null) {
            sModel = new SModel();
        }
        return sModel;
    }

    public void setsModel(SModel sModel) {
        this.sModel = sModel;
    }

    /**
     * Creates new form EngineUI
     */
    public ScrapperEngineUI() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jLabel4 = new javax.swing.JLabel();
        start = new javax.swing.JButton();
        end = new javax.swing.JButton();
        message = new javax.swing.JLabel();
        vpnusername = new javax.swing.JTextField();
        vpnpassword = new javax.swing.JTextField();
        jLabel5 = new javax.swing.JLabel();
        jLabel6 = new javax.swing.JLabel();
        jBStop = new javax.swing.JButton();
        jBDownload = new javax.swing.JButton();
        jTFDownload = new javax.swing.JTextField();
        jLBDate = new javax.swing.JLabel();
        jCBUpdate = new javax.swing.JCheckBox();
        jCBStore = new javax.swing.JCheckBox();

        jLabel4.setText("jLabel4");

        start.setText("Start");
        start.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                startActionPerformed(evt);
            }
        });

        end.setText("Stop & Exit");
        end.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                endActionPerformed(evt);
            }
        });

        jLabel5.setText("Username");

        jLabel6.setText("Password");

        jBStop.setText("Stop");
        jBStop.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBStopActionPerformed(evt);
            }
        });

        jBDownload.setText("Download");
        jBDownload.setToolTipText("");
        jBDownload.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBDownloadActionPerformed(evt);
            }
        });

        jLBDate.setText("Date(2015-02-04)");

        jCBUpdate.setText("Update ");
        jCBUpdate.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jCBUpdateActionPerformed(evt);
            }
        });

        jCBStore.setText("Store");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(message, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addGroup(layout.createSequentialGroup()
                        .addGap(161, 161, 161)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(jLabel5)
                            .addComponent(jLabel6)
                            .addComponent(jLBDate))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(start)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jBStop)
                                .addGap(35, 35, 35)
                                .addComponent(end)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(jBDownload))
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                .addComponent(jTFDownload, javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(vpnpassword, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 294, Short.MAX_VALUE)
                                .addComponent(vpnusername, javax.swing.GroupLayout.Alignment.LEADING))
                            .addComponent(jCBStore)
                            .addComponent(jCBUpdate))
                        .addGap(0, 133, Short.MAX_VALUE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(message, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 146, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(vpnusername, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(vpnpassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel6))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jTFDownload, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLBDate))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jCBUpdate)
                .addGap(2, 2, 2)
                .addComponent(jCBStore)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(start)
                    .addComponent(jBStop)
                    .addComponent(end)
                    .addComponent(jBDownload))
                .addGap(118, 118, 118))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void startActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startActionPerformed
        this.getsModel().setEmail(this.vpnusername.getText());
        this.getsModel().setEmailPassword(this.vpnpassword.getText());
        this.getsModel().setStopEngine(false);
        if(this.userType.equals("8")) {
            this.getsModel().setStore(jCBStore.isSelected());
        } else {
            this.getsModel().setStore(true);
        }        
        sModel.setUsername(username);
        sModel.setPassword(password);

        scrapperWorker = new ScrapperWorker(this.getiNotifier(), this.getsModel());
        scrapperWorker.update();
    }//GEN-LAST:event_startActionPerformed

    private void endActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_endActionPerformed
        try {
            Runtime.getRuntime().exec("taskkill /F /IM java.exe");

        } catch (Throwable ex) {
            log.debug("Error " + ex);
        }
    }//GEN-LAST:event_endActionPerformed

    private void jBStopActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jBStopActionPerformed
        this.getsModel().setStopEngine(true);
    }//GEN-LAST:event_jBStopActionPerformed

    private void jBDownloadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jBDownloadActionPerformed
        BufferedWriter output = null;
        try {
            iNotifier = this.getiNotifier();
            String downloadOptions = jTFDownload.getText();
            if (StringUtils.isBlank(downloadOptions)) {
                iNotifier.notify("Download options missing...");
                return;
            }
            String action = "";
            String startDateRange = "";
            String endDateRange = "";
            String startIdRange = "";
            String endIdRange = "";

            int count = StringUtils.countMatches(downloadOptions, "-");
            if (downloadOptions.trim().equals("*")) {
                action = "*";
            } else if (count == 1) {
                action = "ID";
                String[] parts = downloadOptions.split("-");
                startIdRange = parts[0];
                endIdRange = parts[1];
            } else if (count > 1) {
                action = "D";
                String[] parts = downloadOptions.split("\\|");
                if(parts.length == 2){
                    startDateRange = parts[0] + " 12:00:01";
                    endDateRange = parts[1] + " 23:59:00";
                } else {
                    startDateRange = parts[0] + " 12:00:01";
                    endDateRange = parts[0] + " 23:59:00";
                }
            }

            StringBuilder request = new StringBuilder();
            request.append("<Request>");
            request.append("<username>").append(this.username).append("</username>");
            request.append("<password>").append(this.password).append("</password>");
            request.append("<userid>").append(this.userId).append("</userid>");
            request.append("<action>").append(action).append("</action>");
            request.append("<all>").append("*").append("</all>");

            request.append("<startIdRange>").append(startIdRange).append("</startIdRange>");
            request.append("<endIdRange>").append(endIdRange).append("</endIdRange>");

            request.append("<startDateRange>").append(startDateRange).append("</startDateRange>");
            request.append("<endDateRange>").append(endDateRange).append("</endDateRange>");
            request.append("<working>").append(1).append("</working>");
            request.append("</Request>");

            String req = URLEncoder.encode(request.toString(), "UTF-8");
            String uri = "http://" + IConstant.HOSTNAME + "/index.php?r=scrapper/download";
            String param = "request=" + req;
            String response = HttpHelper.post(new URL(uri), param);

            Document document = DocumentHelper.parseText(response);
            String errorCode = document.valueOf("Response/errorcode");
            String msg = document.valueOf("Response/message");
            if (errorCode.equalsIgnoreCase("001")) {
                iNotifier.notify("Writing in file...");
                File file = new File("c:\\irobot\\scrapper_d.csv");
                List<Node> list = document.selectNodes("/Response/accounts/account");
                output = new BufferedWriter(new FileWriter(file, true));
                for (Node node : list) {
                    output.newLine();
                    String subject = node.valueOf("phone");
                    output.write(subject);
                }
                log.error("Scrapper:downloaded...");
                iNotifier.notify("Done ...");
            } else {
                log.error("Scrapper:Not work...");
            }
            
            /* Update code goes here .... */
            if(!jCBUpdate.isSelected()){
                return;
            }
            uri = "http://" + IConstant.HOSTNAME + "/index.php?r=scrapper/updateScrapper";
            param = "request=" + req;
            response = HttpHelper.post(new URL(uri), param);

            document = DocumentHelper.parseText(response);
            errorCode = document.valueOf("Response/errorcode");
            msg = document.valueOf("Response/message");
            if (errorCode.equalsIgnoreCase("000")) {
                log.error("Scrapper:updated done....");
            }
        } catch (Exception ex) {
            log.error("Scrapper:Run:: stopped causes " + ex);
            ex.printStackTrace();
        } finally {
            if (output != null) {
                try {
                    output.flush();
                    output.close();
                } catch (IOException ex) {
                    iNotifier.notify("Scrapper:Run:: stopped for error: " + ex.getMessage());
                    log.error("Scrapper:Run:: stopped causes " + ex);
                }
            }
        }
    }//GEN-LAST:event_jBDownloadActionPerformed

    private void jCBUpdateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCBUpdateActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_jCBUpdateActionPerformed

    public void initSettings() {
        this.setsModel(null);
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton end;
    private javax.swing.JButton jBDownload;
    private javax.swing.JButton jBStop;
    private javax.swing.JCheckBox jCBStore;
    private javax.swing.JCheckBox jCBUpdate;
    private javax.swing.JLabel jLBDate;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JTextField jTFDownload;
    private javax.swing.JLabel message;
    private javax.swing.JButton start;
    private javax.swing.JTextField vpnpassword;
    private javax.swing.JTextField vpnusername;
    // End of variables declaration//GEN-END:variables

    @Override
    public void notify(final String info) {
        try {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    message.setText(info);
                }
            });
        } catch (Throwable ex) {
            log.debug("notify:: Error causes " + ex.getMessage());
        }
    }

    public INotifier getiNotifier() {
        if (iNotifier == null) {
            iNotifier = this;
        }
        return iNotifier;
    }

    public void setiNotifier(INotifier iNotifier) {
        this.iNotifier = iNotifier;
    }

    @Override
    public void write(String info) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}
